Jeff Bezos 在 2015 年給 Amazon 股東的信裡,把決策分成兩種。
有些決定影響重大,而且幾乎不可逆,像是走過一扇單向門,這種決定要慢慢來、仔細想、多方商量。但大多數決定不是這樣,它們是可以改變、可以回頭的雙向門,就算選錯了,也不必長期承受後果,推開門走回來就好。這種決定應該快快做。
他也提醒,把單向門那套沉重的流程用在雙向門上,代價之一就是實驗做得不夠。
用 agent 寫程式,很多人卡在同一個地方:怕它改壞。
怕它改壞,就不敢讓它大範圍地改;每一步都要確認,每一個檔案都要盯著。一個本來可以讓 agent 試兩種做法、挑好的那個的任務,變成人先想清楚唯一的做法,再一步一步看著它執行。這正是 Bezos 說的那種代價:把雙向門當成單向門處理,實驗就做不起來。
Claude Code 有幾個功能,能把很多原本像單向門的事,變回雙向門。前提是知道哪些門真的退得回來。
每次送出一則訊息開始新的一輪,Claude Code 都會自動記下當下程式碼的狀態,這就是 checkpoint。輸入框空著的時候按兩下 Esc,或是打 /rewind,會列出這次對話裡送過的每一則訊息,選一個時間點,就能決定要退回什麼:只退程式碼、只退對話,或是兩者一起退。
實際用起來是這樣的。請它用某種做法重構一個模組,看完覺得方向不對,就選「程式碼和對話一起退回」,回到下指令之前的狀態。原本那則訊息會被放回輸入框,改一句「改用另一種做法」再送出就好。試錯的成本,從「手動把改動一個一個還原」,變成幾秒鐘。
checkpoint 會跟著對話一起保存,關掉之後再接回這段對話,還是能退回;每段對話保留最近一百個存檔點。
checkpoint 不是萬能的,而且它退不回來的,正好是最需要小心的那些。
它追蹤的,只有 Claude 用自己的檔案編輯工具改過的檔案。透過 shell 指令改動的檔案,例如用 rm 刪掉、用 mv 搬走,checkpoint 不會記錄,也就退不回來。subagent 改的檔案多半也退不回來,要靠 git 還原。自己在編輯器裡手動改的,或是另一個 session 改的,同樣不在範圍內。
檔案以外的事就更不用說了。寫進資料庫的資料、推上遠端的 commit、部署出去的版本、寄出去的通知,這些都是真正的單向門,Claude Code 沒辦法替你退回來。
所以讓 agent 放手試之前,可以先做幾件事。大改之前先 commit 一次,git 才是最可靠的那道雙向門,官方文件也說 checkpoint 不能取代版本控制。需要大量改檔時,請 Claude 用它的編輯工具一個一個改,不要寫一段 shell 腳本批次處理,這樣改動才會被 checkpoint 記下來。至於推送、部署、刪資料這類單向門,Day 8 談過的權限規則就是為它們準備的。例如在權限設定的確認清單加上 Bash(git push *),每次推送前都會先問你;確定永遠不該由 agent 做的,就放進禁止清單。
有時候想比較兩種做法,而不是退回其中一種。
在對話中打 /branch,會把目前為止的對話複製一份,切到新的那一條上繼續;原本的對話原封不動地留著,之後用 /resume 就能切回去。適合的情境是,對話已經累積了很多背景,想在同樣的基礎上試一個不同的方向,又不想失去原本那條路。
/branch 分叉的是對話,兩條對話改的仍然是同一份檔案。要讓兩種做法的程式碼也分開,就要用到下一個功能。
git 的 worktree,是同一個 repo 底下另一個獨立的工作目錄,有自己的檔案和分支。用 claude -w 加上一個名稱啟動,例如 claude -w try-cache,Claude Code 就會在 .claude/worktrees 底下建一個新的 worktree,開一條新分支,在裡面工作。另開一個終端機、換個名稱再啟動一次,就是第二個互不干擾的 session。對話中直接跟 Claude 說「在 worktree 裡做」,它也會自己建一個。
這讓「同時試兩種做法」變得很實際:一個 worktree 用 A 方案,另一個用 B 方案,兩邊都跑完測試,再決定留哪個。不要的那個,結束 session 時選擇移除,連同分支一起刪掉。
有幾件事要先知道。新分支預設是從 repo 的主分支開出來的,不是從手上正在做的分支;如果想在目前的進度上分頭試,要在設定裡把 worktree.baseRef 改成 head。新的 worktree 是一份乾淨的副本,可以直接請 Claude 先在裡面把相依套件裝好。.env 這類沒有進 git 的檔案不會自動帶過去,在專案根目錄放一個 .worktreeinclude,寫法跟 .gitignore 一樣,一行一個,例如 .env,之後每個新的 worktree 都會自動帶上。
要接手同事的 PR 時,也可以用 claude --worktree "#1234" 這樣的寫法,把編號換成 PR 的號碼,直接在一個隔離的 worktree 裡打開它,不會動到手上正在做的東西。# 和引號都要寫,不然 shell 會把 # 後面當成註解。
Bezos 在 2015 年擔心的,是一間公司因為怕犯錯,把每個決定都當成走不回來的門,最後什麼都不敢試。
agent 寫程式的時代,這個擔心換了一個樣子出現:因為怕它改壞,就盯著它的每一步。大改前 commit 一次,多數的門就能回頭;真正回不了頭的那幾扇,交給權限規則把關。剩下的,就讓它放手去試。
延伸閱讀
把「哪些門真的退得回來」分清楚這點很實用。我會再驗證一個邊界:/rewind 退的是檔案編輯,但 agent 跑過的 shell 指令(刪檔、改資料庫、裝套件)退不回去。可以在測試專案讓它先跑一個有副作用的指令再 rewind,看狀態有沒有一起還原。確認過邊界,再決定哪些任務可以放手讓它試,哪些要先用 git commit 或分支當保險。